#pragma once

#include "tnl.h" 
#include "tnlEventConnection.h" 
#include "tnlNetInterface.h" 
#include "tnlRPC.h" 
#include "NetworkConnection.h"
#include "NetworkPackets.h"
#include <string>
#include <list>


// Some shorthands after all
using TNL::StringPtr;
using TNL::U16;
using TNL::U32;
using TNL::F32;


namespace Putin{


/*!
 * \brief
 * Implements all RPC procedures in both directions
 * 
 * THE RtsConnection class defines the methods for communication of 
 * generic RTS game messages that are later translated to the accurate
 * in game commands
 * 
 * \remarks
 * The same implementation goes for client and server.
 */
class RtsConnection : public TNL::EventConnection, public NetworkConnection
{
private:
	typedef TNL::EventConnection Parent;

private: 

	TNL::RefPtr<TNL::NetInterface>	mNetInterface;

public:

	TNL_DECLARE_NETCONNECTION(RtsConnection);

	// == RPC CLIENT TO SERVER procedures ==
	TNL_DECLARE_RPC( rpcCSText, (U16 id1, U16 id2, StringPtr text));
	TNL_DECLARE_RPC( rpcCSCommand, (U16 id1,U16 id2, U16 command, F32 x, F32 y));

	// == RPC SERVER TO CLIENT ==
	TNL_DECLARE_RPC( rpcSCText, (U16 id1, U16 id2, StringPtr text));
	TNL_DECLARE_RPC( rpcSCCommand, (U16 id1, U16 id2, U16 command, F32 x, F32 y));

public:
	RtsConnection(void);
	virtual ~RtsConnection(void);

	// Implement NetworkConnection
	void broadcast(NetworkPacket* np, bool skipEcho=true);
	void send2Client(NetworkPacket* np);
	void send2Server(NetworkPacket* np);
	void addHandler(NetFunctorB* nf);
	void addOnConnectHandler( NetFunctorB* nf);
	void addOnDisconnectedHandler(NetFunctorB* nf);
	std::string getRemoteAddress();


	// Control functions
	bool startClient(TNL::Address address);
	bool startServer(TNL::Address address);

	void checkMessages();

protected:

	void 	onConnectionEstablished ();
	void	onConnectionTerminated(TNL::NetConnection::TerminationReason tr, const char* errorStr);
	void	onConnectTerminated(TNL::NetConnection::TerminationReason tr, const char* rejectionStr);

	static RtsConnection* mMainServerConn;
	std::list<NetFunctorB*> mHandlers;
	std::list<NetFunctorB*> mConnectHandlers;
	std::list<NetFunctorB*> mDisconnectedHandlers;

	/*!
	 * \brief Retrieve the real connection 
	 * 
	 * \returns The "real" RtsConnection for this type of object
	 * 
	 * Retrieve the real instance of this class for usage with 
	 * callbacks. In the client case, this is the "this" pointer 
	 * as expected. However, a server has num clients + 1 connections
	 * This retrievs the "main" connection where the callback handels 
	 * are registred, regardles of client or server.
	 */
	RtsConnection*			getMainConn();
	bool					mIsClient;
};


} // End Namespace Putin
 